home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rsynth / src / say.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  7.5 KB  |  390 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. #include "proto.h"
  7. #include "parwave.h"
  8. #include "hplay.h"
  9. #include "dict.h"
  10. #include "ASCII.h"
  11. #include "darray.h"
  12. #include "holmes.h"
  13. #include "phtoelm.h"
  14. #include "text.h"
  15. #include "say.h"
  16.  
  17. int synthesis_model = ALL_PARALLEL;
  18. long nfcascade = 4;
  19. long nspfr;
  20. long sigmx;
  21. long warnsw, dispt, disptcum;
  22. int bDebug = 0;
  23. FILE *debug1, *debug2;
  24.  
  25. dict_t *dict;
  26.  
  27. unsigned
  28. spell_out(word, n, phone)
  29. char *word;
  30. int n;
  31. darray_ptr phone;
  32. {
  33.  unsigned nph = 0;
  34.  fprintf(stderr, "Spelling '%.*s'\n", n, word);
  35.  while (n-- > 0)
  36.   {
  37.    nph += xlate_string(ASCII[toascii(*word++)], phone);
  38.   }
  39.  return nph;
  40. }
  41.  
  42. int
  43. suspect_word(s, n)
  44. char *s;
  45. int n;
  46. {
  47.  int i = 0;
  48.  int seen_lower = 0;
  49.  int seen_upper = 0;
  50.  int seen_vowel = 0;
  51.  int last = 0;
  52.  for (i = 0; i < n; i++)
  53.   {
  54.    char ch = *s++;
  55.    if (i && last != '-' && isupper(ch))
  56.     seen_upper = 1;
  57.    if (islower(ch))
  58.     {
  59.      seen_lower = 1;
  60.      ch = toupper(ch);
  61.     }
  62.    if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' || ch == 'Y')
  63.     seen_vowel = 1;
  64.    last = ch;
  65.   }
  66.  return !seen_vowel || (seen_upper && seen_lower) || !seen_lower;
  67. }
  68.  
  69. static unsigned xlate_word PROTO((char *word, int n, darray_ptr phone));
  70.  
  71.  
  72. static unsigned
  73. xlate_word(word, n, phone)
  74. char *word;
  75. int n;
  76. darray_ptr phone;
  77. {
  78.  unsigned nph = 0;
  79.  if (*word != '[')
  80.   {
  81.    if (dict)
  82.     {
  83.      dictrec_ptr p = spell_find(dict, word, n);
  84.      if (p)
  85.       {
  86.        char *s = p->pronounce;
  87.        char *e = p->pronounce + sizeof(p->pronounce);
  88. #if 0
  89.        fprintf(stderr, "Dict '%.*s'\n", n, word);
  90. #endif
  91.        /* may need to modify dictionary's idea of phonemes here,
  92.           as (for example) final :-> /'faInl/ does not work as it stands.
  93.           This is probably part of a deeper problem concerning
  94.           which allophone to use for a particular phoneme in context.
  95.        */
  96.        while (e > s && isspace(e[-1]))
  97.         e--;
  98.        while (s < e)
  99.         phone_append(phone, *s++);
  100.        phone_append(phone, ' ');
  101.        return nph + 1;
  102.       }
  103.      else
  104.       {
  105.        /* If supposed word contains '.' or '-' try breaking it up...*/
  106.        char *h = word;
  107.        while (h < word + n)
  108.         {
  109.          if (*h == '.' || *h == '-')
  110.           {
  111.            nph += xlate_word(word, h++ - word, phone);
  112.            nph += xlate_word(h, word + n - h, phone);
  113.            return nph;
  114.           }
  115.          else
  116.           h++;
  117.         }
  118.       }
  119.     }
  120.    if (suspect_word(word, n))
  121.     return spell_out(word, n, phone);
  122.    else
  123.     {
  124.      fprintf(stderr, "Guess '%.*s'\n", n, word);
  125.      nph += NRL(word, n, phone);
  126.     }
  127.   }
  128.  else
  129.   {
  130.    if ((++word)[(--n) - 1] == ']')
  131.     n--;
  132.    while (n-- > 0)
  133.     {
  134.      phone_append(phone,*word++);
  135.      nph++;
  136.     }
  137.   }
  138.  phone_append(phone, ' ');
  139.  return nph + 1;
  140. }
  141.  
  142.  
  143. void
  144. say_phones(phone, len)
  145. char *phone;
  146. int len;
  147. {
  148.  darray_t elm;
  149.  unsigned frames;
  150.  darray_init(&elm, sizeof(char), len);
  151.  if ((frames = phone_to_elm(phone, len, &elm)))
  152.   {
  153.    unsigned max_samples = frames * nspfr;
  154.    short *samp = (short *) malloc(sizeof(short) * max_samples);
  155.    printf("%.*s\n", len, phone);
  156.    if (samp)
  157.     {
  158.      unsigned nsamp = holmes(elm.items, (unsigned char *) darray_find(&elm, 0),
  159.                              max_samples, samp);
  160.      audio_play(nsamp, samp);
  161.      free(samp);
  162.     }
  163.   }
  164.  darray_free(&elm);
  165. }
  166.  
  167. unsigned
  168. xlate_string(string, phone)
  169. char *string;
  170. darray_ptr phone;
  171. {
  172.  unsigned nph = 0;
  173.  char *s = string;
  174.  char ch;
  175.  while (isspace(ch = *s))
  176.   s++;
  177.  while ((ch = *s))
  178.   {
  179.    char *word = s;
  180.    if (isalpha(ch))
  181.     {
  182.      while (isalpha(ch = *s) || ((ch == '\'' || ch == '-' || ch == '.') && isalpha(s[1])))
  183.       s++;
  184.      if (!ch || isspace(ch) || ispunct(ch) || (isdigit(ch) && !suspect_word(word, s - word)))
  185.       nph += xlate_word(word, s - word, phone);
  186.      else
  187.       {
  188.        while ((ch = *s) && !isspace(ch) && !ispunct(ch))
  189.         s++;
  190.        nph += spell_out(word, s - word, phone);
  191.       }
  192.     }
  193.    else if (isdigit(ch) || (ch == '-' && isdigit(s[1])))
  194.     {
  195.      int sign = (ch == '-') ? -1 : 1;
  196.      long value = 0;
  197.      if (sign < 0)
  198.       ch = *++s;
  199.      while (isdigit(ch = *s))
  200.       {
  201.        value = value * 10 + ch - '0';
  202.        s++;
  203.       }
  204.      if (ch == '.' && isdigit(s[1]))
  205.       {
  206.        word = ++s;
  207.        nph += xlate_cardinal(value * sign, phone);
  208.        nph += xlate_string("point", phone);
  209.        while (isdigit(ch = *s))
  210.         s++;
  211.        nph += spell_out(word, s - word, phone);
  212.       }
  213.      else
  214.       {
  215.        /* check for ordinals, date, time etc. can go in here */
  216.        nph += xlate_cardinal(value * sign, phone);
  217.       }
  218.     }
  219.    else if (ch == '[' && strchr(s,']'))
  220.     {char *word = s;
  221.      while (*s && *s++ != ']')
  222.       /* nothing */;
  223.      nph += xlate_word(word, s - word, phone);
  224.     }
  225.    else if (ispunct(ch))
  226.     {
  227.      switch (ch)
  228.       {
  229.         /* On end of sentence flush the buffer ... */
  230.        case '!':
  231.        case '?':
  232.        case '.':
  233.         if ((!s[1] || isspace(s[1])) && phone->items)
  234.          {
  235.           say_phones((char *) darray_find(phone, 0), phone->items);
  236.           phone->items = 0;
  237.          }
  238.         s++;
  239.         phone_append(phone, ' ');
  240.         break;
  241.        case '"':               /* change pitch ? */
  242.        case ':':
  243.        case '-':
  244.        case ';':
  245.        case ',':
  246.        case '(':
  247.        case ')':
  248.         s++;
  249.         phone_append(phone, ' ');
  250.         break;
  251.        case '[':  
  252.         {char *e = strchr(s,']');
  253.          if (e)
  254.           {
  255.            s++;
  256.            while (s < e)
  257.             phone_append(phone,*s++);
  258.            s = e+1;
  259.            break;
  260.           }
  261.         }
  262.        default:
  263.         nph += spell_out(word, 1, phone);
  264.         s++;
  265.         break;
  266.       }
  267.     }
  268.    else
  269.     {
  270.      while ((ch = *s) && !isspace(ch))
  271.       s++;
  272.      nph += spell_out(word, s - word, phone);
  273.     }
  274.    while (isspace(ch = *s))
  275.     s++;
  276.   }
  277.  return nph;
  278. }
  279.  
  280. char *
  281. concat_args(argc, argv)
  282. int argc;
  283. char *argv[];
  284. {
  285.  int len = 0;
  286.  int i;
  287.  char *buf;
  288.  for (i = 1; i < argc; i++)
  289.   len += strlen(argv[i]) + 1;
  290.  buf = (char *) malloc(len);
  291.  if (buf)
  292.   {
  293.    char *d = buf;
  294.    for (i = 1; i < argc;)
  295.     {
  296.      char *s = argv[i++];
  297.      while (*s)
  298.       *d++ = *s++;
  299.      if (i < argc)
  300.       *d++ = ' ';
  301.      else
  302.       *d = '\0';
  303.     }
  304.   }
  305.  return buf;
  306. }
  307.  
  308. void
  309. say_string(s)
  310. char *s;
  311. {
  312.  darray_t phone;
  313.  darray_init(&phone, sizeof(char), 128);
  314.  xlate_string(s, &phone);
  315.  if (phone.items)
  316.   say_phones((char *) darray_find(&phone, 0), phone.items);
  317.  darray_free(&phone);
  318. }
  319.  
  320. extern int darray_fget PROTO((FILE *f, darray_ptr p));
  321.  
  322. int
  323. darray_fget(f, p)
  324. FILE *f;
  325. darray_ptr p;
  326. {
  327.  int ch;
  328.  while ((ch = fgetc(f)) != EOF)
  329.   {
  330.    phone_append(p, ch);
  331.    if (ch == '\n')
  332.     break;
  333.   }
  334.  phone_append(p, '\0');
  335.  return p->items - 1;
  336. }
  337.  
  338. extern void say_file PROTO((FILE *f));
  339.  
  340. void
  341. say_file(f)
  342. FILE *f;
  343. {
  344.  darray_t line;
  345.  darray_t phone;
  346.  darray_init(&line, sizeof(char), 128);
  347.  darray_init(&phone, sizeof(char), 128);
  348.  while (darray_fget(f, &line))
  349.   {
  350.    xlate_string((char *) darray_find(&line, 0), &phone);
  351.    line.items = 0;
  352.   }
  353.  if (phone.items)
  354.   say_phones((char *) darray_find(&phone, 0), phone.items);
  355.  darray_free(&phone);
  356.  darray_free(&line);
  357. }
  358.  
  359. int main PROTO((int argc, char *argv[], char *env[]));
  360.  
  361. int
  362. main(argc, argv, env)
  363. int argc;
  364. char *argv[];
  365. char *env[];
  366. {
  367.  dict_t d;
  368.  argc = audio_init(argc, argv);
  369.  argc = init_synth(argc, argv);
  370.  argc = init_holmes(argc, argv);
  371.  if (dict_init(&d, NULL))
  372.   dict = &d;
  373.  if (argc > 1)
  374.   {
  375.    char *s = concat_args(argc, argv);
  376.    if (s)
  377.     {
  378.      say_string(s);
  379.      free(s);
  380.     }
  381.   }
  382.  else
  383.   say_file(stdin);
  384.  audio_term();
  385.  term_holmes();
  386.  if (dict)
  387.   dict_term(dict);
  388.  return (0);
  389. }
  390.